<?php
namespace Matrix;

/**
 * HTML辅助类
 *
 * 辅助HTML
 */
class HTML
{
	/**
	 * 自定义宏命令
	 *
	 * @var array
	 */
	public static $macros = array();
	
	/**
	 * 注册一个宏命令
	 *
	 * @param	string	$name
	 * @param	Closure	$macro
	 * @return	void
	 */
	public static function extend($name, \Closure $macro)
	{
		$this->macros[$name] = $macro;
	}
	
	/**
	 * 转换HTML字符串为实体
	 *
	 * @param	string	$value
	 * @return	string
	 */
	public static function entities($value)
	{
		return htmlentities($value, ENT_QUOTES, Config::get('application.encoding'), false);
	}
	
	/**
	 * 转换实体为HTML字符串
	 *
	 * @param	string	$value
	 * @return	string
	 */
	public static function decode($value)
	{
		return html_entity_decode($value, ENT_QUOTES, Config::get('application.encoding'));
	}
	
	/**
	 * 生成JS链接
	 *
	 * @param	string	$url
	 * @param	array	$attributes
	 * @return	string
	 */
	public static function script($url, $attributes = array())
	{
		$defaults = array('type' => 'text/javascript');
		$attributes += $defaults;
		$url = URL::to_asset($url);
		return '<script src="'.$url.'"'.static::attributes($attributes).'></script>'.PHP_EOL;
	}
	
	/**
	 * 生成CSS链接
	 *
	 * @param	string	$url
	 * @param	array	$attributes
	 * @return	string
	 */
	public static function style($url, $attributes = array())
	{
		$defaults = array('media' => 'all', 'type' => 'text/css', 'rel' => 'stylesheet');
		$attributes += $defaults;
		$url = URL::to_asset($url);
		return '<link href="'.$url.'"'.static::attributes($attributes).'>'.PHP_EOL;
	}
	
	/**
	 * 生成span标签
	 *
	 * @param	string	$value
	 * @param	array	$attributes
	 * @return	string
	 */
	public static function span($value, $attributes = array())
	{
		return '<span'.static::attributes($attributes).'>'.static::entities($value).'</span>';
	}
	
	/**
	 * 生成一个链接
	 *
	 * @param	string	$url
	 * @param	string	$title
	 * @param	array	$attributes
	 * @param	boolean	$https
	 * @return	string
	 */
	public static function link($url, $title, $attributes = array(), $https = false)
	{
		$url = URL::to($url, $https);
		return '<a href="'.$url.'"'.static::attributes($attributes).'>'.static::entities($title).'</a>';
	}
	
	/**
	 * 生成一个HTTPS安全链接
	 *
	 * @param	string	$url
	 * @param	string	$title
	 * @param	array	$attributes
	 * @return	string
	 */
	public static function link_to_secure($url, $title, $attributes = array())
	{
		return static::link($url, $title, $attributes, true);
	}
	
	/**
	 * 生成一个资源管理的链接
	 *
	 * @param	string	$url
	 * @param	string	$title
	 * @param	array	$attributes
	 * @param	boolean	$https
	 * @return	string
	 */
	public static function link_to_asset($url, $title, $attributes = array(), $https = null)
	{
		$url = URL::to_asset($url, $https);
		return '<a href="'.$url.'"'.static::attributes($attributes).'>'.static::entities($title).'</a>';
	}
	
	/**
	 * 生成一个安全的资源管理链接
	 *
	 * @param	string	$url
	 * @param	string	$title
	 * @param	array	$attributes
	 * @return	string
	 */
	public static function link_to_secure_asset($url, $title, $attributes = array())
	{
		return static::link_to_asset($url, $title, $attributes, true);
	}
	
	/**
	 * 根据一个路由生成一个链接
	 *
	 * @param	string	$name
	 * @param	string	$title
	 * @param	array	$parameters
	 * @param	array	$attributes
	 * @return	string
	 */
	public static function link_to_route($name, $title, $parameters = array(), $attributes = array())
	{
		return static::link(URL::to_route($name, $parameters), $title, $attributes);
	}
	
	/**
	 * 根据一个控制器生成一个链接
	 *
	 * @param	string	$action
	 * @param	string	$title
	 * @param	array	$parameters
	 * @param	array	$attributes
	 * @return	string
	 */
	public static function link_to_action($action, $title, $parameters = array(), $attributes = array())
	{
		return static::link(URL::to_action($action, $parameters), $title, $attributes);
	}
	
	/**
	 * 生成mailto
	 *
	 * @param	string	$email
	 * @param	string	$title
	 * @param	array	$attributes
	 * @return	string
	 */
	public static function mailto($email, $title = null, $attributes = array())
	{
		$email = static::email($email);
		if ($title === $email) {
			$title = $email;
		}
		$email = '&#109;&#097;&#105;&#108;&#116;&#111;&#058;'.$email;
		return '<a href="'.$email.'"'.static::attributes($attributes).'>'.static::entities($title).'</a>';
	}
	
	/**
	 * Obfuscate an e-mail address to prevent spam-bots from sniffing it.
	 * 模糊邮箱, 防止被采集
	 *
	 * @param	string	$email
	 * @return	string
	 */
	public static function email($email)
	{
		return str_replace('@', '&#64;', static::obfuscate($email));
	}
	
	/**
	 * 生成IMG
	 *
	 * @param	string	$url
	 * @param	string	$alt
	 * @param	array	$attributes
	 * @return	string
	 */
	public static function image($url, $alt = '', $attributes = array())
	{
		$attributes['alt'] = $alt;
		return '<img src="'.URL::to_asset($url).'"'.static::attributes($attributes).'>';
	}
	
	/**
	 * 生成ORDER LIST
	 *
	 * @param	string	$list
	 * @param	array	$attributes
	 * @return	string
	 */
	public static function ol($list, $attributes = array())
	{
		return static::listing('ol', $list, $attributes);
	}
	
	/**
	 * 生成UNORDER LIST
	 *
	 * @param	string	$list
	 * @param	array	$attributes
	 * @return	string
	 */
	public static function ul($list, $attributes = array())
	{
		return static::listing('ul', $list, $attributes);
	}
	
	/**
	 * 生成属性
	 *
	 * @param	string	$attributes
	 * @return	string
	 */
	public static function attributes($attributes)
	{
		$html = array();
		foreach ((array) $attributes as $key => $value) {
			if (is_numeric($key)) {
				$key = $value;
			}
			if ($value !== null) {
				$html[] = $key.'="'.static::entities($value).'"';
			}
		}
		return !empty($html) > 0 ? ' '.implode(' ', $html) : '';
	}
	
	/**
	 * 模糊一个字符串防止被机器采集
	 *
	 * @param	string	$value
	 * @return	string
	 */
	protected static function obfuscate($value)
	{
		$safe = '';
		foreach (str_split($value) as $letter) {
			switch (mt_rand(1, 3)) {
				case 1:
					$safe .= '&#'.ord($letter).';';
					break;
				case 2:
					$safe .= '&#x'.dechex(ord($letter)).';';
					break;
				case 3:
					$safe .= $letter;
			}
		}
		return $safe;
	}
	
	/**
	 * 生成一个order or unorder list
	 *
	 * @param	string	$type
	 * @param	mixed	$list
	 * @param	array	$attributes
	 * @retrun	string
	 */
	protected static function listing($type, $list, $attributes = array())
	{
		$html = '';
		if (empty($list)) {
			return $html;
		}
		foreach ($list as $key => $value) {
			if (is_array($value)) {
				$html .= static::listing($type, $value);
			} else {
				$html .= '<li>'.static::entities($value).'</li>';
			}
		}
		return '<'.$type.static::attributes($attributes).'>'.$html.'</'.$type.'>';
	}
	
	/**
	 * 静态调用自定义的宏命令
	 *
	 * @param	string	$method
	 * @param	array	$parameters
	 * @return	string
	 * @throws	Exception
	 */
	public static function __callStatic($method, $parameters)
	{
		if (isset(static::$macros[$method])) {
			return call_user_func_array(static::$macros[$method], $parameters);
		}
		throw new \Exception("Method [$method] does not exist.");
	}
}